home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / inetutil.1 / inetutil / inetutils-1.1 / libtelnet / rsaencpwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-31  |  12.4 KB  |  496 lines

  1. /*-
  2.  * Copyright (c) 1992, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)rsaencpwd.c    8.3 (Berkeley) 5/30/95";
  36. #endif /* not lint */
  37.  
  38. #ifdef HAVE_CONFIG_H
  39. #include <config.h>
  40. #endif
  41.  
  42. #ifdef    RSA_ENCPWD
  43. /*
  44.  * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
  45.  * ALL RIGHTS RESERVED
  46.  *
  47.  * "Digital Equipment Corporation authorizes the reproduction,
  48.  * distribution and modification of this software subject to the following
  49.  * restrictions:
  50.  *
  51.  * 1.  Any partial or whole copy of this software, or any modification
  52.  * thereof, must include this copyright notice in its entirety.
  53.  *
  54.  * 2.  This software is supplied "as is" with no warranty of any kind,
  55.  * expressed or implied, for any purpose, including any warranty of fitness
  56.  * or merchantibility.  DIGITAL assumes no responsibility for the use or
  57.  * reliability of this software, nor promises to provide any form of
  58.  * support for it on any basis.
  59.  *
  60.  * 3.  Distribution of this software is authorized only if no profit or
  61.  * remuneration of any kind is received in exchange for such distribution.
  62.  *
  63.  * 4.  This software produces public key authentication certificates
  64.  * bearing an expiration date established by DIGITAL and RSA Data
  65.  * Security, Inc.  It may cease to generate certificates after the expiration
  66.  * date.  Any modification of this software that changes or defeats
  67.  * the expiration date or its effect is unauthorized.
  68.  *
  69.  * 5.  Software that will renew or extend the expiration date of
  70.  * authentication certificates produced by this software may be obtained
  71.  * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
  72.  * 94065, (415)595-8782, or from DIGITAL"
  73.  *
  74.  */
  75.  
  76. #include <sys/types.h>
  77. #include <arpa/telnet.h>
  78. #include <pwd.h>
  79. #include <stdio.h>
  80.  
  81. #ifdef    __STDC__
  82. #include <stdlib.h>
  83. #endif
  84. #ifdef    NO_STRING_H
  85. #include <strings.h>
  86. #else
  87. #include <string.h>
  88. #endif
  89. #include <crypt.h>
  90.  
  91. #include "encrypt.h"
  92. #include "auth.h"
  93. #include "misc.h"
  94. #include "cdc.h"
  95.  
  96. extern auth_debug_mode;
  97.  
  98. static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
  99.                       AUTHTYPE_RSA_ENCPWD, };
  100. static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
  101.                     TELQUAL_NAME, };
  102.  
  103. #define    RSA_ENCPWD_AUTH    0    /* Authentication data follows */
  104. #define    RSA_ENCPWD_REJECT    1    /* Rejected (reason might follow) */
  105. #define RSA_ENCPWD_ACCEPT    2    /* Accepted */
  106. #define    RSA_ENCPWD_CHALLENGEKEY    3    /* Challenge and public key */
  107.  
  108. #define NAME_SZ   40
  109. #define CHAL_SZ   20
  110. #define PWD_SZ    40
  111.  
  112. static    KTEXT_ST auth;
  113. static    char name[NAME_SZ];
  114. static    char user_passwd[PWD_SZ];
  115. static  char key_file[2*NAME_SZ];
  116. static  char lhostname[NAME_SZ];
  117. static char  challenge[CHAL_SZ];
  118. static int   challenge_len;
  119.  
  120.     static int
  121. Data(ap, type, d, c)
  122.     Authenticator *ap;
  123.     int type;
  124.     void *d;
  125.     int c;
  126. {
  127.         unsigned char *p = str_data + 4;
  128.     unsigned char *cd = (unsigned char *)d;
  129.  
  130.     if (c == -1)
  131.         c = strlen((char *)cd);
  132.  
  133.         if (0) {
  134.                 printf("%s:%d: [%d] (%d)",
  135.                         str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
  136.                         str_data[3],
  137.                         type, c);
  138.                 printd(d, c);
  139.                 printf("\r\n");
  140.         }
  141.     *p++ = ap->type;
  142.     *p++ = ap->way;
  143.     if (type != NULL) *p++ = type;
  144.         while (c-- > 0) {
  145.                 if ((*p++ = *cd++) == IAC)
  146.                         *p++ = IAC;
  147.         }
  148.         *p++ = IAC;
  149.         *p++ = SE;
  150.     if (str_data[3] == TELQUAL_IS)
  151.         printsub('>', &str_data[2], p - (&str_data[2]));
  152.         return(net_write(str_data, p - str_data));
  153. }
  154.  
  155.     int
  156. rsaencpwd_init(ap, server)
  157.     Authenticator *ap;
  158.     int server;
  159. {
  160.     char  *cp;
  161.     FILE  *fp;
  162.  
  163.     if (server) {
  164.         str_data[3] = TELQUAL_REPLY;
  165.         memset(key_file, 0, sizeof(key_file));
  166.         gethostname(lhostname, sizeof(lhostname));
  167.         if ((cp = strchr(lhostname, '.')) != 0)  *cp = '\0';
  168.         strcpy(key_file, "/etc/.");
  169.         strcat(key_file, lhostname);
  170.         strcat(key_file, "_privkey");
  171.         if ((fp=fopen(key_file, "r"))==NULL) return(0);
  172.         fclose(fp);
  173.     } else {
  174.         str_data[3] = TELQUAL_IS;
  175.     }
  176.     return(1);
  177. }
  178.  
  179.     int
  180. rsaencpwd_send(ap)
  181.     Authenticator *ap;
  182. {
  183.  
  184.     printf("[ Trying RSAENCPWD ... ]\n");
  185.     if (!UserNameRequested) {
  186.         return(0);
  187.     }
  188.     if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
  189.         return(0);
  190.     }
  191.     if (!Data(ap, NULL, (void *)NULL, 0)) {
  192.         return(0);
  193.     }
  194.  
  195.  
  196.     return(1);
  197. }
  198.  
  199.     void
  200. rsaencpwd_is(ap, data, cnt)
  201.     Authenticator *ap;
  202.     unsigned char *data;
  203.     int cnt;
  204. {
  205.     Session_Key skey;
  206.     Block datablock;
  207.     char  r_passwd[PWD_SZ], r_user[NAME_SZ];
  208.     char  *cp, key[160];
  209.     char  chalkey[160], *ptr;
  210.     FILE  *fp;
  211.     int r, i, j, chalkey_len, len;
  212.     time_t now;
  213.  
  214.     cnt--;
  215.     switch (*data++) {
  216.     case RSA_ENCPWD_AUTH:
  217.         memmove((void *)auth.dat, (void *)data, auth.length = cnt);
  218.  
  219.         if ((fp=fopen(key_file, "r"))==NULL) {
  220.           Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
  221.           auth_finished(ap, AUTH_REJECT);
  222.           return;
  223.         }
  224.         /*
  225.          *  get privkey
  226.          */
  227.         fscanf(fp, "%x;", &len);
  228.         for (i=0;i<len;i++) {
  229.           j = getc(fp);  key[i]=j;
  230.         }
  231.         fclose(fp);
  232.  
  233.         r = accept_rsa_encpwd(&auth, key, challenge,
  234.                       challenge_len, r_passwd);
  235.         if (r < 0) {
  236.           Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
  237.           auth_finished(ap, AUTH_REJECT);
  238.           return;
  239.         }
  240.         auth_encrypt_userpwd(r_passwd);
  241.         if (rsaencpwd_passwdok(UserNameRequested, UserPassword) == 0) {
  242.           /*
  243.            *  illegal username and password
  244.            */
  245.           Data(ap, RSA_ENCPWD_REJECT, (void *)"Illegal password", -1);
  246.           auth_finished(ap, AUTH_REJECT);
  247.           return;
  248.         }
  249.  
  250.         Data(ap, RSA_ENCPWD_ACCEPT, (void *)0, 0);
  251.         auth_finished(ap, AUTH_USER);
  252.         break;
  253.  
  254.  
  255.     case IAC:
  256.  
  257.         /*
  258.          * If we are doing mutual authentication, get set up to send
  259.          * the challenge, and verify it when the response comes back.
  260.          */
  261.         if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
  262.           register int i;
  263.  
  264.  
  265.           time(&now);
  266.           if ((now % 2) == 0) {
  267.             sprintf(challenge, "%x", now);
  268.             challenge_len = strlen(challenge);
  269.           } else {
  270.             strcpy(challenge, "randchal");
  271.             challenge_len = 8;
  272.           }
  273.  
  274.           if ((fp=fopen(key_file, "r"))==NULL) {
  275.             Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
  276.             auth_finished(ap, AUTH_REJECT);
  277.             return;
  278.           }
  279.           /*
  280.            *  skip privkey
  281.            */
  282.           fscanf(fp, "%x;", &len);
  283.           for (i=0;i<len;i++) {
  284.             j = getc(fp);
  285.           }
  286.           /*
  287.            * get pubkey
  288.            */
  289.           fscanf(fp, "%x;", &len);
  290.           for (i=0;i<len;i++) {
  291.             j = getc(fp);  key[i]=j;
  292.           }
  293.           fclose(fp);
  294.           chalkey[0] = 0x30;
  295.           ptr = (char *) &chalkey[1];
  296.           chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len;
  297.           EncodeLength(ptr, chalkey_len);
  298.           ptr +=NumEncodeLengthOctets(chalkey_len);
  299.           *ptr++ = 0x04;  /* OCTET STRING */
  300.           *ptr++ = challenge_len;
  301.           memmove(ptr, challenge, challenge_len);
  302.           ptr += challenge_len;
  303.           *ptr++ = 0x04;  /* OCTET STRING */
  304.           EncodeLength(ptr, i);
  305.           ptr += NumEncodeLengthOctets(i);
  306.           memmove(ptr, key, i);
  307.           chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len;
  308.           Data(ap, RSA_ENCPWD_CHALLENGEKEY, (void *)chalkey, chalkey_len);
  309.         }
  310.         break;
  311.         
  312.     default:
  313.         Data(ap, RSA_ENCPWD_REJECT, 0, 0);
  314.         break;
  315.     }
  316. }
  317.  
  318.  
  319.     void
  320. rsaencpwd_reply(ap, data, cnt)
  321.     Authenticator *ap;
  322.     unsigned char *data;
  323.     int cnt;
  324. {
  325.     Session_Key skey;
  326.     KTEXT_ST token;
  327.     Block enckey;
  328.     int r, pubkey_len;
  329.     char        randchal[CHAL_SZ], *cp;
  330.     char        chalkey[160], pubkey[128], *ptr;
  331.  
  332.     if (cnt-- < 1)
  333.         return;
  334.     switch (*data++) {
  335.     case RSA_ENCPWD_REJECT:
  336.         if (cnt > 0) {
  337.             printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n",
  338.                 cnt, data);
  339.         } else
  340.             printf("[ RSA_ENCPWD refuses authentication ]\r\n");
  341.         auth_send_retry();
  342.         return;
  343.     case RSA_ENCPWD_ACCEPT:
  344.         printf("[ RSA_ENCPWD accepts you ]\n");
  345.         auth_finished(ap, AUTH_USER);
  346.         return;
  347.     case RSA_ENCPWD_CHALLENGEKEY:
  348.         /*
  349.          * Verify that the response to the challenge is correct.
  350.          */
  351.  
  352.         memmove((void *)chalkey, (void *)data, cnt);
  353.         ptr = (char *) &chalkey[0];
  354.         ptr += DecodeHeaderLength(chalkey);
  355.         if (*ptr != 0x04) {
  356.                   return;
  357.                 }
  358.         *ptr++;
  359.         challenge_len = DecodeValueLength(ptr);
  360.         ptr += NumEncodeLengthOctets(challenge_len);
  361.         memmove(challenge, ptr, challenge_len);
  362.         ptr += challenge_len;
  363.         if (*ptr != 0x04) {
  364.                   return;
  365.                 }
  366.                 *ptr++;
  367.         pubkey_len = DecodeValueLength(ptr);
  368.         ptr += NumEncodeLengthOctets(pubkey_len);
  369.         memmove(pubkey, ptr, pubkey_len);
  370.         memset(user_passwd, 0, sizeof(user_passwd));
  371.         local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
  372.         UserPassword = user_passwd;
  373.         Challenge = challenge;
  374.         r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey);
  375.         if (r < 0) {
  376.           token.length = 1;
  377.         }
  378.  
  379.         if (!Data(ap, RSA_ENCPWD_AUTH, (void *)token.dat, token.length)) {
  380.           return;
  381.         }
  382.  
  383.         break;
  384.  
  385.     default:
  386.         return;
  387.     }
  388. }
  389.  
  390.     int
  391. rsaencpwd_status(ap, name, level)
  392.     Authenticator *ap;
  393.     char *name;
  394.     int level;
  395. {
  396.  
  397.     if (level < AUTH_USER)
  398.         return(level);
  399.  
  400.     if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) {
  401.         strcpy(name, UserNameRequested);
  402.         return(AUTH_VALID);
  403.     } else {
  404.         return(AUTH_USER);
  405.     }
  406. }
  407.  
  408. #define    BUMP(buf, len)        while (*(buf)) {++(buf), --(len);}
  409. #define    ADDC(buf, len, c)    if ((len) > 0) {*(buf)++ = (c); --(len);}
  410.  
  411.     void
  412. rsaencpwd_printsub(data, cnt, buf, buflen)
  413.     unsigned char *data, *buf;
  414.     int cnt, buflen;
  415. {
  416.     char lbuf[32];
  417.     register int i;
  418.  
  419.     buf[buflen-1] = '\0';        /* make sure its NULL terminated */
  420.     buflen -= 1;
  421.  
  422.     switch(data[3]) {
  423.     case RSA_ENCPWD_REJECT:    /* Rejected (reason might follow) */
  424.         strncpy((char *)buf, " REJECT ", buflen);
  425.         goto common;
  426.  
  427.     case RSA_ENCPWD_ACCEPT:    /* Accepted (name might follow) */
  428.         strncpy((char *)buf, " ACCEPT ", buflen);
  429.     common:
  430.         BUMP(buf, buflen);
  431.         if (cnt <= 4)
  432.             break;
  433.         ADDC(buf, buflen, '"');
  434.         for (i = 4; i < cnt; i++)
  435.             ADDC(buf, buflen, data[i]);
  436.         ADDC(buf, buflen, '"');
  437.         ADDC(buf, buflen, '\0');
  438.         break;
  439.  
  440.     case RSA_ENCPWD_AUTH:        /* Authentication data follows */
  441.         strncpy((char *)buf, " AUTH", buflen);
  442.         goto common2;
  443.  
  444.     case RSA_ENCPWD_CHALLENGEKEY:
  445.         strncpy((char *)buf, " CHALLENGEKEY", buflen);
  446.         goto common2;
  447.  
  448.     default:
  449.         sprintf(lbuf, " %d (unknown)", data[3]);
  450.         strncpy((char *)buf, lbuf, buflen);
  451.     common2:
  452.         BUMP(buf, buflen);
  453.         for (i = 4; i < cnt; i++) {
  454.             sprintf(lbuf, " %d", data[i]);
  455.             strncpy((char *)buf, lbuf, buflen);
  456.             BUMP(buf, buflen);
  457.         }
  458.         break;
  459.     }
  460. }
  461.  
  462. int rsaencpwd_passwdok(name, passwd)
  463.      char *name, *passwd;
  464. {
  465.   char *salt, *p;
  466.   struct passwd *pwd;
  467.   int   passwdok_status = 0;
  468.  
  469.   if (pwd = getpwnam(name))
  470.     salt = pwd->pw_passwd;
  471.   else salt = "xx";
  472.  
  473.   p = CRYPT (passwd, salt);
  474.  
  475.   if (pwd && !strcmp(p, pwd->pw_passwd)) {
  476.     passwdok_status = 1;
  477.   } else passwdok_status = 0;
  478.   return(passwdok_status);
  479. }
  480.  
  481. #endif
  482.  
  483. #ifdef notdef
  484.  
  485. prkey(msg, key)
  486.     char *msg;
  487.     unsigned char *key;
  488. {
  489.     register int i;
  490.     printf("%s:", msg);
  491.     for (i = 0; i < 8; i++)
  492.         printf(" %3d", key[i]);
  493.     printf("\r\n");
  494. }
  495. #endif
  496.